#include "cutils.h"

#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QApplication>
#include <QJsonParseError>
#include <QImage>
#include <QByteArray>
#include <QPixmap>
#include <QBuffer>

/**
 * 计算给定字符串在指定字体下的宽度。
 * 
 * @param font 指定的QFont对象，用于计算字符串的宽度。
 * @param str 指定的QString对象，需要计算其在指定字体下的宽度。
 * @return 返回字符串在指定字体下的宽度，如果字符串为空，则返回0。
 */
int WidthWithFixString(QFont font, QString str) {
  // 检查字符串是否为空，如果为空直接返回0
  if (str.isEmpty()) {
    return 0;
  }

  QFontMetrics metrix(font); // 创建QFontMetrics对象，用于获取字体的度量信息
  QRect font_rect = metrix.boundingRect(str); // 获取字符串在指定字体下的边界矩形
  return font_rect.width(); // 返回边界矩形的宽度，即字符串的宽度
}

/**
 * 根据指定宽度调整字体大小，以确保字符串能完全显示在给定宽度内。
 * 如果字符串长度超过给定宽度，则通过截断字符串并添加后缀的方式来适应宽度。
 * 
 * @param font 要调整的字体。
 * @param width 指定的宽度，单位通常为像素。
 * @param str 需要显示的字符串。
 * @param suffix 截断字符串后添加的后缀，例如"..."。
 * @return 调整后的字符串，如果输入的宽度足够显示原字符串，则返回原字符串。
 */
QString FontAdjustWidth(QFont font, int width, QString str, QString suffix) {
    if (width == 0 || str.isEmpty()) {
        // 输入信息不完整，直接返回原字符串
        return str;
    }

    QFontMetrics metrix(font);
    QRect font_rect_str = metrix.boundingRect(str);

    int iterations = 0; // 添加计数器变量

    // 设置最大迭代次数，防止无限循环
    int maxIterations = 1000;

    if(str.length()>18){
        while (width < font_rect_str.width()) {
            iterations++;
        // 如果达到最大迭代次数，则退出循环
        if (iterations >= maxIterations) {
            break;
        }
        if (str.length() < 3) {
            return str;
        }
        str = str.left(str.length() - 3);
        font_rect_str = metrix.boundingRect(str);
        }
        return str+suffix;
    }
    else{
        return str;
    }
}


QString variantToString(const QVariant &variant, int precision) {
    auto type = variant.type();
    switch (type) {
    case QVariant::Invalid:
        return "Invalid";
    case QVariant::Bool:
        return variant.toBool() ? "true" : "false";
    case QVariant::Int:
        return decimalStrDirectlyTruncated(QString::number(variant.toInt(), 'f', 6),precision);
    case QVariant::UInt:
        return decimalStrDirectlyTruncated(QString::number(variant.toUInt(), 'f', 6),precision);
    case QVariant::LongLong:
        return decimalStrDirectlyTruncated(QString::number(variant.toLongLong(), 'f', 6),precision);
    case QVariant::ULongLong:
        return decimalStrDirectlyTruncated(QString::number(variant.toULongLong(), 'f', 6),precision);
    case QVariant::Double:
        return decimalStrDirectlyTruncated(QString::number(variant.toDouble(), 'f', 6),precision);
    case QVariant::String:
        return variant.toString();
    case QVariant::ByteArray:
        return QString::fromUtf8(variant.toByteArray());
    case 38: // QVariant::Float
        return decimalStrDirectlyTruncated(QString::number(variant.toFloat(), 'f', 6),precision);
    default:
        return "Unsupported type";
    }
}

QMultiMap<int, QString> multiMapValueUniqueness(const QMultiMap<int, QString>& multiMap) {
    QMultiMap<int, QString> out;
    for (auto it = multiMap.constBegin(); it != multiMap.constEnd(); ++it) {
        if(out.contains(it.key(),it.value()))
            continue;
        out.insert(it.key(),it.value());
    }
    return out;
}

QJsonObject string2Json(const QString &jsonString)
{
    // 将 QString 转换为 QByteArray
    QByteArray byteArray = jsonString.toUtf8();

    // 通过 QJsonDocument 解析 QByteArray
    QJsonParseError error;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &error);

    // 检查解析是否成功
    if (error.error != QJsonParseError::NoError) {
        qDebug() << "Error parsing JSON:" << error.errorString();
        return QJsonObject();
    }

    // 检查解析后的对象是否是 JSON 对象
    if (!jsonDoc.isObject()) {
        qDebug() << "JSON document is not an object.";
        return QJsonObject();
    }

    // 将 QJsonDocument 转换为 QJsonObject
    QJsonObject jsonObject = jsonDoc.object();

    return jsonObject;
}

QString decimalStrDirectlyTruncated(QString decimalStr, int precision)
{
    auto dotPos = decimalStr.indexOf(".");
    if(precision>0)
        decimalStr = decimalStr.mid(0,dotPos+precision+1);
    else if(0 == precision)
        decimalStr = decimalStr.mid(0,dotPos);
    return decimalStr;
}

QString encodeImageToBase64(const QPixmap &pixmap)
{
    QImage image = pixmap.toImage();
    if(image.isNull()){
        return QString();
    }
    QByteArray imageBytes;
    QBuffer buffer(&imageBytes);
    if(!buffer.open(QIODevice::WriteOnly)){
        return QString();
    }
    if(!image.save(&buffer, "PNG")){
        buffer.close();
        return QString();
    }
    buffer.close();
    //将图片数据编码为Base64字符串
    QString base64Image = imageBytes.toBase64();
    return base64Image;
}
